package com.ls.bpmn.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ls.bpmn.dto.*;
import com.ls.bpmn.entity.BpmnProcinst;
import org.apache.ibatis.annotations.*;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author lisheng
 * @Date 2025/05/07 01:05
 **/
public interface BpmnProcessMapper extends BaseMapper<BpmnProcinst> {
    /**
     * 流转记录获取接口
     * @param processInstanceId
     * @param parentActInstId
     * @return
     */
    List<HistoricActivityInstanceDTO> selectHistoricActivityInstanceDTO(@Param("processInstanceId") String processInstanceId,
                                                                        @Param("parentActInstId") String parentActInstId);

    /**
     * 获取流程实例当前活动节点信息
     * @param processInstanceIds
     * @return
     */
    @Select({"<script>select a.proc_inst_id_ as processInstanceId,",
            "    wm_concat(distinct a.act_id_) as nodes,",
            "    wm_concat(distinct a.act_name_) as names,",
            "    wm_concat(distinct t.assignee_) as assignees,",
            "    wm_concat(distinct i.user_id_) as candidates",
            "  from act_hi_actinst a",
            "    inner join act_ru_execution e on e.id_ = a.execution_id_",
            "    left join act_ru_task t on a.task_id_ = t.id_",
            "    left join act_ru_identitylink i ON t.id_ = i.task_id_",
            "  where a.act_type_ in('userTask', 'serviceTask', 'receiveTask')",
            "    and a.end_time_ is null",
            "    <if test='processInstanceIds != null &amp;&amp; processInstanceIds.size() > 0'>",
            "       and a.proc_inst_id_ in",
            "       <foreach item='item' index='index' collection='processInstanceIds' open='(' separator=',' close=')'>",
            "       #{item}",
            "       </foreach>",
            "    </if> group by a.proc_inst_id_",
            "</script>"})
    @ResultType(value = HashMap.class)
    @MapKey("processInstanceId")
    @Results({
            @Result(column = "processInstanceId", property = "processInstanceId"),
            @Result(column = "nodes", property = "nodes"),
            @Result(column = "names", property = "names"),
            @Result(column = "assignees", property = "assignees"),
            @Result(column = "candidates", property = "candidates"),
    })
    Map<String, ActivityInstanceDTO> selectActivityInstanceDTO(@Param("processInstanceIds")List<String> processInstanceIds);

    /**
     * 全部工单列表
     * @return
     */
    List<TaskListDTO> selectWorkOrder(
            Page<TaskListDTO> page,
            @Param("userId") String userId,
            @Param("processDefinitionId") String processDefinitionId,
            @Param("keys") List<String> keys,
            @Param("businessKey") String businessKey,
            @Param("handle") Boolean handle,
            @Param("nodeName") String nodeName,
            @Param("startDate") Date startDate,
            @Param("endDate") Date endDate,
            @Param("state") Integer state,
            @Param("groupIds") List<String> groupIds,
            @Param("conditions") List<ConditionDTO> conditions);

    @Select({
            "<script>",
            "SELECT COUNT(1) FROM (",
            "SELECT DISTINCT t.id_ FROM act_ru_task t",
            "INNER JOIN act_hi_procinst p ON p.id_ = t.proc_inst_id_",
            "<if test='businessKey != null'>",
            "AND p.business_key_ = #{businessKey}",
            "</if>",
            "INNER JOIN act_re_procdef d ON t.proc_def_id_ = d.id_",
            "<if test='processDefinitionId != null'>",
            "AND d.id_ = #{processDefinitionId}",
            "</if>",
            "<if test='keys != null and keys.size() > 0'>",
            "AND d.key_ IN",
            "<foreach item='item' index='index' collection='keys' open='(' separator=',' close=')'>",
            "#{item}",
            "</foreach>",
            "</if>",
            "<if test='assigned == null'>",
            "LEFT JOIN act_ru_identitylink i ON i.task_id_ = t.id_",
            "</if>",
            "<if test='assigned == false'>",
            "INNER JOIN act_ru_identitylink i ON i.task_id_ = t.id_",
            "</if>",
            "WHERE t.priority_ > 0",
            "<if test='userId != null'>",
            "<if test='assigned != null and assigned == false'>",
            "AND (t.assignee_ IS NULL AND i.type_ = 'candidate'",
            "AND (i.user_id_ = #{userId}",
            "<if test='groupIds != null and groupIds.size() > 0'>",
            "OR i.GROUP_ID_ IN",
            "<foreach item='groupId' index='index' collection='groupIds' open='(' separator=',' close=')'>",
            "#{groupId}",
            "</foreach>",
            "</if>",
            "))",
            "</if>",
            "<if test='assigned != null and assigned == true'>",
            "AND t.assignee_ = #{userId}",
            "</if>",
            "<if test='assigned == null'>",
            "AND ((t.assignee_ IS NOT NULL AND t.assignee_ = #{userId})",
            "OR (t.assignee_ IS NULL AND i.type_ = 'candidate'",
            "AND (i.user_id_ = #{userId}",
            "<if test='groupIds != null and groupIds.size() > 0'>",
            "OR i.GROUP_ID_ IN",
            "<foreach item='groupId' index='index' collection='groupIds' open='(' separator=',' close=')'>",
            "#{groupId}",
            "</foreach>",
            "</if>",
            ")))",
            "</if>",
            "</if>",
            "<if test='taskName != null'>",
            "AND t.name_ LIKE #{taskName}",
            "</if>",
            "<if test='conditions != null and conditions.size() > 0'>",
            "<foreach item='c' index='index' collection='conditions'>",
            "AND EXISTS (",
            "SELECT id_ FROM act_ru_variable",
            "WHERE name_ = #{c.name}",
            "AND proc_inst_id_ = t.proc_inst_id_",
            "<choose>",
            "<when test='c.type == \"string\"'>",
            "AND text_ IS NOT NULL",
            "<choose>",
            "<when test='c.operator == \"eq\"'>AND text_ = #{c.value}</when>",
            "<when test='c.operator == \"neq\"'>AND text_ != #{c.value}</when>",
            "<when test='c.operator == \"gt\"'>AND text_ &gt; #{c.value}</when>",
            "<when test='c.operator == \"gteq\"'>AND text_ &gt;= #{c.value}</when>",
            "<when test='c.operator == \"lt\"'>AND text_ &lt; #{c.value}</when>",
            "<when test='c.operator == \"lteq\"'>AND text_ &lt;= #{c.value}</when>",
            "<when test='c.operator == \"like\"'>AND text_ LIKE '%' || #{c.value} || '%'</when>",
            "</choose>",
            "</when>",
            "<when test='c.type == \"integer\" || c.type == \"boolean\" || c.type == \"date\"'>",
            "AND long_ IS NOT NULL",
            "<choose>",
            "<when test='c.operator == \"eq\"'>AND long_ = #{c.value}</when>",
            "<when test='c.operator == \"neq\"'>AND long_ != #{c.value}</when>",
            "<when test='c.operator == \"gt\"'>AND long_ &gt; #{c.value}</when>",
            "<when test='c.operator == \"gteq\"'>AND long_ &gt;= #{c.value}</when>",
            "<when test='c.operator == \"lt\"'>AND long_ &lt; #{c.value}</when>",
            "<when test='c.operator == \"lteq\"'>AND long_ &lt;= #{c.value}</when>",
            "</choose>",
            "</when>",
            "<when test='c.type == \"double\"'>",
            "AND double_ IS NOT NULL",
            "<choose>",
            "<when test='c.operator == \"eq\"'>AND double_ = #{c.value}</when>",
            "<when test='c.operator == \"neq\"'>AND double_ != #{c.value}</when>",
            "<when test='c.operator == \"gt\"'>AND double_ &gt; #{c.value}</when>",
            "<when test='c.operator == \"gteq\"'>AND double_ &gt;= #{c.value}</when>",
            "<when test='c.operator == \"lt\"'>AND double_ &lt; #{c.value}</when>",
            "<when test='c.operator == \"lteq\"'>AND double_ &lt;= #{c.value}</when>",
            "</choose>",
            "</when>",
            "</choose>",
            ")",
            "</foreach>",
            "</if>",
            ") sub",
            "</script>"
    })
    Long selectTodoTaskCount(
            @Param("userId") String userId,
            @Param("processDefinitionId") String processDefinitionId,
            @Param("keys") List<String> keys,
            @Param("businessKey") String businessKey,
            @Param("taskName") String taskName,
            @Param("assigned") Boolean assigned,
            @Param("groupIds") List<String> groupIds,
            @Param("conditions") List<ConditionDTO> conditions
    );

    /**
     * 代办任务列表
     * @return
     */
    List<TaskDTO> selectTodoTask(
            Page<TaskDTO> page,
            @Param("userId") String userId,
            @Param("processDefinitionId") String processDefinitionId,
            @Param("keys") List<String> keys,
            @Param("businessKey") String businessKey,
            @Param("taskName") String taskName,
            @Param("assigned") Boolean assigned,
            @Param("groupIds") List<String> groupIds,
            @Param("conditions") List<ConditionDTO> conditions,
            @Param("startDate") Date startDate,
            @Param("endDate") Date endDate,
            @Param("orderBy") String orderBy,
            @Param("sort") String sort
    );

    /**
     * 已办任务列表
     * @return
     */
    List<TaskDTO> selectDoneTask(
            Page<TaskDTO> page,
            @Param("userId") String userId,
            @Param("processDefinitionId") String processDefinitionId,
            @Param("keys") List<String> keys,
            @Param("businessKey") String businessKey,
            @Param("taskName") String taskName,
            @Param("conditions") List<ConditionDTO> conditions,
            @Param("startDate") Date startDate,
            @Param("endDate") Date endDate,
            @Param("orderBy") String orderBy,
            @Param("sort") String sort
    );}
